/* Copyright (c) 2015,2016 Lucky Byte, Inc.
 */
package com.lucky_byte.pay.jar.pa01;

import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.DefaultHandler;

import com.google.gson.JsonObject;
import com.lucky_byte.pay.jar.Packet;

/**
 * 兴业扫码支付报文
 */
public class PacketA01 extends Packet
{
	private static final Logger logger = LogManager.getLogger();
	private String encoding;
	private Map<String, String> fset;

	public PacketA01() {
		this.fset = new HashMap<>();
	}

	@Override
	public boolean has(String name) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public String get(String name) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public boolean set(String name, String value) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public int count() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public List<String> keySet() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void remove(String name) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void clear() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public Packet clone() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public JsonObject toJson() {
		// TODO Auto-generated method stub
		return null;
	}

	/**
	 * 解析报文数据
	 */
	public boolean parse(String data) {
		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			factory.setNamespaceAware(false);
			SAXParser parser = factory.newSAXParser();
			XMLReader reader = parser.getXMLReader();
			XmlHandler handler = new XmlHandler(this);
			reader.setContentHandler(handler);
			reader.setErrorHandler(new XmlErrorHandler(data));
			reader.setProperty(
					"http://xml.org/sax/properties/lexical-handler", handler);
			reader.parse(new InputSource(new StringReader(data)));
			logger.info("共读取[{}]个字段.", this.fset.size());
			return true;
		} catch (UnsupportedEncodingException e) {
			logger.error("报文设置的字符编码[{}]无效.", encoding);
			return false;
		} catch (Exception e) {
			logger.error("解析报文错误[{}].", e.getMessage());
			return false;
		}
	}

}


class XmlHandler extends DefaultHandler implements LexicalHandler
{
	private static final Logger logger = LogManager.getLogger();
	private Packet packet;
	private int level;
	private StringBuilder text;

	public XmlHandler(Packet packet) {
		this.packet = packet;
	}

	public void startDocument() throws SAXException {
		level = 0;
		text = new StringBuilder();
	}

	public void endDocument() throws SAXException {
	}

	public void startElement(String namespaceURI, String localName,
			String qName,  Attributes atts) throws SAXException {
		level++;
		if (level == 1) {
			return;
		}
		if (level > 2) {
			logger.error("报文格式错误，XML节点嵌套层次大于2.");
			throw new SAXException("报文格式错误，XML节点嵌套层次大于2");
		}
	}

	public void endElement(String uri, String localName, String qName)	
			throws SAXException {
		if (level == 2) {
			logger.info("读取字段[{}][{}].", qName, text.toString().trim());
			packet.set(qName, text.toString().trim());
		}
		text.setLength(0);
		level--;
	}

	public void characters(char ch[], int start, int length)
			throws SAXException {
		text.append(new String(ch, start, length));
	}

	@Override
	public void startDTD(String name, String publicId, String systemId)
			throws SAXException {
	}

	@Override
	public void endDTD() throws SAXException {
	}

	@Override
	public void startEntity(String name) throws SAXException {
	}

	@Override
	public void endEntity(String name) throws SAXException {
	}

	@Override
	public void startCDATA() throws SAXException {
	}

	@Override
	public void endCDATA() throws SAXException {
	}

	@Override
	public void comment(char[] ch, int start, int length)
			throws SAXException {
	}
}


class XmlErrorHandler implements ErrorHandler
{
	private static final Logger logger = LogManager.getLogger();

	private String data;

	public XmlErrorHandler(String data) {
		this.data = data;
	}

	@Override
	public void warning(SAXParseException exception) throws SAXException {
		logger.warn("解析[{}]第[{}]行警告[{}].", data,
				exception.getLineNumber(), exception.getMessage());
	}

	@Override
	public void error(SAXParseException exception) throws SAXException {
		logger.warn("解析[{}]第[{}]行错误[{}].", data,
				exception.getLineNumber(), exception.getMessage());
		throw new SAXException(exception);
	}

	@Override
	public void fatalError(SAXParseException exception) throws SAXException {
		logger.warn("解析[{}]第[{}]行严重错误[{}].", data,
				exception.getLineNumber(), exception.getMessage());
		throw new SAXException(exception);
	}
}
